#include <http_server_ros.h>
#include <stdlib.h>
#define BUF_MAX 1024*16
#define MAP_MAX 10
#define MAP_BUF_MAX 500*1024*1024	//500M
#define UNINITIALIZED 1
#define INITIALIZED   2
#define STARTED       3
#define STOPPED       4

#define HTTP_SUCCESS    200
#define HTTP_ERROR      403

struct event_base *http_server_base;
struct evhttp *http_server_evhttp;
int http_server_flag = 0;
thread http_server_thread;

string map_path;
CloudApi *cloud_api;
char map_buf[MAP_BUF_MAX];

int httpserver_bindsocket(int port, int backlog);
int httpserver_start(int port, int nthreads, int backlog);
void* httpserver_Dispatch(void *arg);
void httpserver_GenericHandler(struct evhttp_request *req, void *arg);
void httpserver_ProcessRequest(struct evhttp_request *req);
 
int httpserver_bindsocket(int port, int backlog) {
  int r;
  int nfd;
  nfd = socket(AF_INET, SOCK_STREAM, 0);
  if (nfd < 0) return -1;
 
  int one = 1;
  r = setsockopt(nfd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int));
 
  struct sockaddr_in addr;
  memset(&addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = INADDR_ANY;
  addr.sin_port = htons(port);
 
  r = bind(nfd, (struct sockaddr*)&addr, sizeof(addr));
  if (r < 0) return -1;
  r = listen(nfd, backlog);
  if (r < 0) return -1;
 
  int flags;
  if ((flags = fcntl(nfd, F_GETFL, 0)) < 0
      || fcntl(nfd, F_SETFL, flags | O_NONBLOCK) < 0)
    return -1;
 
  return nfd;
}
 
int httpserver_start(int port, int nthreads, int backlog) {
  int r, i;
  int nfd = httpserver_bindsocket(port, backlog);
  if (nfd < 0) return -1;
  pthread_t ths[nthreads];
  for (i = 0; i < nthreads; i++) {
    struct event_base *base = event_init();
    if (base == NULL) return -1;
    struct evhttp *httpd = evhttp_new(base);
    if (httpd == NULL) return -1;
    r = evhttp_accept_socket(httpd, nfd);
    if (r != 0) return -1;
    evhttp_set_gencb(httpd, httpserver_GenericHandler, NULL);
    r = pthread_create(&ths[i], NULL, httpserver_Dispatch, base);
    if (r != 0) return -1;
  }
  for (i = 0; i < nthreads; i++) {
    //pthread_join(ths[i], NULL);
	pthread_detach(ths[i]);
  }
}
 
void* httpserver_Dispatch(void *arg) {
  event_base_dispatch((struct event_base*)arg);
  return NULL;
}
 
void httpserver_GenericHandler(struct evhttp_request *req, void *arg) {
      httpserver_ProcessRequest(req);
}

void httpserver_ProcessRequest(struct evhttp_request *req) {
    evhttp_cmd_type req_type = req->type;    // req_type = evhttp_request_get_command(req);

    if (req_type == EVHTTP_REQ_POST)
    {
        http_post_handler(req);
    }
    else if (req_type == EVHTTP_REQ_GET)
    {
        http_get_handler(req);
    }
    else
    {

    }
}


int http_server_init(const char *http_addr, short http_port)
{
	http_server_base = event_base_new();

	http_server_evhttp = evhttp_new(http_server_base);
	if(!http_server_evhttp)
	{
		return -1;
	}

	int ret = evhttp_bind_socket(http_server_evhttp, http_addr, http_port);
	if(ret != 0)
	{
		return -1;
	}

	evhttp_set_gencb(http_server_evhttp, generic_handler, NULL);

	http_server_thread = thread([](){
		prctl(PR_SET_NAME, "http_server");
		http_server_flag = STARTED;
		event_base_dispatch(http_server_base);
	}); 

	http_server_flag = INITIALIZED;
	return 0;
}
int http_server_start()
{
    http_server_thread.detach();    // tcp_client_thread: join
    return 0;
}
int http_server_stop()
{
	event_base_loopbreak(http_server_base);
	evhttp_free(http_server_evhttp);
	event_base_free(http_server_base);
}
void http_default_handler(struct evhttp_request *req)
{
    struct evbuffer *databuf = evbuffer_new();
    evbuffer_add_printf(databuf, "Error: Invalid http request type");
    evhttp_send_reply(req, 0, "error", databuf);
    evbuffer_free(databuf);
}

void generic_handler(struct evhttp_request *req, void *arg)
{
    evhttp_cmd_type req_type = req->type;    // req_type = evhttp_request_get_command(req);

    if (req_type == EVHTTP_REQ_POST)
    {
        http_post_handler(req);
    }
    else if (req_type == EVHTTP_REQ_GET)
    {
        http_get_handler(req);
    }
    else
    {
        http_default_handler(req);
    }
}

//解析http头，主要用于get请求时解析uri和请求参数
const char *find_http_header(struct evhttp_request *req,string & query)
{
	if(req == NULL)
	{
		printf("====line:%d,%s\n",__LINE__,"input params is null.");
		return NULL;
	}
	
	struct evhttp_uri *decoded = NULL;

	const char *path;
	const char *uri = evhttp_request_get_uri(req);//获取请求uri
	
	if(uri == NULL)
	{
		printf("====line:%d,evhttp_request_get_uri return null\n",__LINE__);
		return NULL;
	}
	
	//解码uri
	decoded = evhttp_uri_parse(uri);
	if (!decoded) 
	{
		printf("====line:%d,It's not a good URI. Sending BADREQUEST\n",__LINE__);
		evhttp_send_error(req, HTTP_BADREQUEST, 0);
		return NULL;
	}
	//获取uri中的path部分
	path = evhttp_uri_get_path(decoded);
	if (path == NULL) 
	{
		path = "/";
	}

	const char* query_ = evhttp_uri_get_query(decoded);
	if(query_ != NULL)
		query = query_;

	return path;
}

//解析post请求数据
const char * get_post_message(char *buf, struct evhttp_request *req)
{
	size_t post_size = 0;

	struct evhttp_uri *decoded = NULL;

	const char *path;
	const char *uri = evhttp_request_get_uri(req);//获取请求uri
	
	if(uri == NULL)
	{
		printf("====line:%d,evhttp_request_get_uri return null\n",__LINE__);
		return NULL;
	}
	
	//解码uri
	decoded = evhttp_uri_parse(uri);
	if (!decoded) 
	{
		printf("====line:%d,It's not a good URI. Sending BADREQUEST\n",__LINE__);
		evhttp_send_error(req, HTTP_BADREQUEST, 0);
		return NULL;
	}
	//获取uri中的path部分
	path = evhttp_uri_get_path(decoded);
	if (path == NULL) 
	{
		path = "/";
	}
	
	post_size = evbuffer_get_length(req->input_buffer);//获取数据长度

	if (post_size <= 0 || post_size >= MAP_BUF_MAX)
	{
		printf("====line:%d,post msg is empty or too large!\n",__LINE__);
		return "ERROR";
	}
	else
	{
		string path_ = path;
		if(path_ == "/update_map")
		{
			ROS_INFO("post_size:%d",post_size);
			struct evkeyvalq *tmp = evhttp_request_get_input_headers(req);
			const char *value = evhttp_find_header(tmp,"filename");
			ROS_INFO("filename:%s",value);
			memcpy(map_buf, evbuffer_pullup(req->input_buffer,-1), post_size);
			string filename = value;
			int index = filename.find(".");
			string filename_ = filename.substr(0,index);
			ROS_INFO("filename_:%s",filename_.c_str());
/*			bool start = false;

			for(int i=0;i<post_size;i++)
			{
				if(map_buf[i]=='f'&&map_buf[i+1]=='i'&&map_buf[i+2]=='l'&&map_buf[i+3]=='e'&&
					map_buf[i+4]=='n'&&map_buf[i+5]=='a'&&map_buf[i+6]=='m'&&map_buf[i+7]=='e'&&
					map_buf[i+8]=='='&&map_buf[i+9]=='\"')
				{
					int k = i+10;			
					while(map_buf[k] != '.' && k<200)
						filename += map_buf[k++];
					break;
				}
			}
			char buuuf[200];
			for(int i=0;i<200;i++)
			{
				buuuf[i] = map_buf[i];
			}
			std::cout<<buuuf<<std::endl;
*/			ofstream outfile;
			if(true)//is_map_exsit()
			{
				outfile.open(map_path+filename_+"/"+filename_+".pgm",ios::out);
			}

			if(outfile.is_open())
			{
				int begin = 0;
				int end = post_size;
				for(int i=0;i<post_size;i++)
				{
					if(map_buf[i] == 'P' && map_buf[i+1]=='2')
					{
						begin = i;
						break;
					}
				}
				for(int i=post_size-100;i<post_size-1;i++)
				{
					if(map_buf[i] == '-' && map_buf[i+1]=='-')
					{
						end = i-2;
						break;
					}
				}
				for(int i=begin;i<=end;i++)
				{
					outfile<< map_buf[i];	
				}
				outfile.close();
			}	
			return path;
		}
		size_t copy_len = post_size > BUF_MAX ? BUF_MAX : post_size;		
		memcpy(buf, evbuffer_pullup(req->input_buffer,-1), copy_len);
		buf[post_size] = '\0';
	}
	return path;
}



//处理get请求
void http_get_handler(struct evhttp_request *req)
{
	if(req == NULL)
	{
		printf("====line:%d,%s\n",__LINE__,"input param req is null.");
		return;
	}
	struct evkeyvalq params = {0};
	//common param
	struct evbuffer *retbuff = NULL;
	retbuff = evbuffer_new();
	string reply;

	string query_str = "";
	const char *path = find_http_header(req, query_str);
	string path_str = path;
	ROS_INFO("get:%s",path_str.c_str());
	if(path_str == "/get_id")
	{
		ptree id = getMac();
		reply =  ptree_to_string(id);
	}
	else if(path_str == "/get_map_list")
	{
		reply = get_map_list();
	}
	else if(path_str == "/get_map_png")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);	
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		ptree map_png;
		int code;
		string reason = "success";
		if(get_map_png(map_path+map_name+"/"+map_name+".png",retbuff,code,reason))
		{
			evhttp_add_header(req->output_headers, "Content-Type", "image/png; charset=UTF-8");
			evhttp_send_reply(req, code, reason.c_str(), retbuff);
			evbuffer_free(retbuff);
			return;
		}
		else{
			map_png.put<string>("data","",string_translator<std::string>());
			map_png.put<string>("errorCode","NOT_FOUND",string_translator<std::string>());
			map_png.put<string>("msg","failed",string_translator<std::string>());
			map_png.put<bool>("successed",false);
			reply =  ptree_to_string(map_png);
		}
	}
	else if(path_str == "/get_map_pcd")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);	
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;

		ptree map_pcd;
		int code;
		string reason = "success";

		if(get_map_pcd(map_path+map_name+"/"+map_name+".pcd",retbuff,code,reason))
		{

			evhttp_add_header(req->output_headers, "Content-Type", "application/octet-stream; charset=UTF-8");
			evhttp_send_reply(req, code, reason.c_str(), retbuff);
			evbuffer_free(retbuff);

			return;
		}
		else{
			map_pcd.put<string>("data","",string_translator<std::string>());
			map_pcd.put<string>("errorCode","NOT_FOUND",string_translator<std::string>());
			map_pcd.put<string>("msg","failed",string_translator<std::string>());
			map_pcd.put<bool>("successed",false);
			reply =  ptree_to_string(map_pcd);
		}
	}
	else if(path_str == "/get_map_pgm")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);	
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		
		ptree map_pgm;
		int code;
		string reason = "success";

		if(get_map_pgm(map_path+map_name+"/"+map_name+".pgm",retbuff,code,reason))
		{
			string str = "filename="+ map_name + "; charset=UTF-8";
//			string str = "filename="+ map_name;
			evhttp_add_header(req->output_headers, "Content-Disposition", str.c_str());
			evhttp_add_header(req->output_headers, "Content-Type", "image/x-portable-graymap; charset=UTF-8");
			evhttp_send_reply(req, code, reason.c_str(), retbuff);
			evbuffer_free(retbuff);
			return;
		}
		else{
			map_pgm.put<string>("data","",string_translator<std::string>());
			map_pgm.put<string>("errorCode","NOT_FOUND",string_translator<std::string>());
			map_pgm.put<string>("msg","failed",string_translator<std::string>());
			map_pgm.put<bool>("successed",false);
			reply =  ptree_to_string(map_pgm);
		}
	}
	else if(path_str == "/get_param")
	{
		if(query_str == "")
		{
			string map_name = "";
			ptree param = get_param(map_name);	
			reply =  ptree_to_string(param);
		}
		else
		{
			char *query = const_cast<char*>(query_str.c_str());
			evhttp_parse_query_str(query, &params);			
			char *query_result = (char*)evhttp_find_header(&params, "map_name");
			string map_name = query_result;
			ptree param = get_param(map_name);
			reply =  ptree_to_string(param);
		}
	}
	else if(path_str == "/edit_map")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		ptree info = edit_map(map_name);
		reply = ptree_to_string(info);
	}
	else if(path_str == "/load_map")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = load_map(map_name);
	}
	else if(path_str == "/load_map_status")
	{
		ptree info = get_load_map_status();;
		reply = ptree_to_string(info);
	}
	else if(path_str == "/init_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_init_point(map_name);			
	}
	else if(path_str == "/calibration_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_calibration_point(map_name);			
	}
	else if(path_str == "/work_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_work_point(map_name);			
	}	
	else if(path_str == "/charge_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_charge_point(map_name);			
	}
	else if(path_str == "/user_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_user_point(map_name);			
	}	
	else if(path_str == "/navi_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_navi_point(map_name);			
	}
	else if(path_str == "/del_navi_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		char *query_result2 = (char*)evhttp_find_header(&params, "point_name");
		string point_name = query_result2;
		ptree navi_point = del_navi_point(map_name,point_name);			
		reply =  ptree_to_string(navi_point);
	}
	else if(path_str == "/navi_path")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_navi_path(map_name);
	}
	else if(path_str == "/virtual_wall")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);	
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_virtual_wall(map_name);
	}
	else if(path_str == "/virtual_wall_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_virtual_wall_point(map_name);
	}
	else if(path_str == "/user_path")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_user_path(map_name);
	}
	else if(path_str == "/user_path_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_user_path_point(map_name);
	}
	else if(path_str == "/slow_area")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_slow_area(map_name);
	}
	else if(path_str == "/slow_area_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_slow_area_point(map_name);
	}
	else if(path_str == "/stop_area")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_stop_area(map_name);
	}
	else if(path_str == "/stop_area_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_stop_area_point(map_name);
	}
	else if(path_str == "/user_area")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_user_area(map_name);
	}
	else if(path_str == "/user_area_point")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		reply = get_user_area_point(map_name);
	}

	else if(path_str == "/del_navi_path")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		char *query_result2 = (char*)evhttp_find_header(&params, "path_name");
		string path_name = query_result2;
		ptree navi_point = del_navi_path(map_name,path_name);			
		reply =  ptree_to_string(navi_point);
	}
	else if(path_str == "/get_task")
	{
		ptree task = get_task();			
		reply =  ptree_to_string(task);
	}
	else if(path_str == "/del_task")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		char *query_result2 = (char*)evhttp_find_header(&params, "task_name");
		string task_name = query_result2;
		ptree task = del_task(map_name,task_name);			
		reply =  ptree_to_string(task);
	}
	else if(path_str == "/get_default_task")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		ptree task = get_default_task(map_name);			
		reply =  ptree_to_string(task);
	}
	else if(path_str == "/del_default_task")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		ptree task = del_default_task(map_name);			
		reply =  ptree_to_string(task);
	}
	else if(path_str == "/head_mode")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "cmd");
		string cmd = query_result;
		ptree mode = set_head_mode(cmd);			
		reply =  ptree_to_string(mode);
	}
	else if(path_str == "/charge_cmd")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "cmd");
		string cmd = query_result;
		ptree charge_cmd = set_charge_cmd(cmd);			
		reply =  ptree_to_string(charge_cmd);
	}
	else if(path_str == "/manual_mode")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "cmd");
		string cmd = query_result;
		ptree manual_mode = set_manual_mode(cmd);			
		reply =  ptree_to_string(manual_mode);
	}

	else if(path_str == "/get_status")
	{
		ptree status = get_status();			
		reply =  ptree_to_string(status);
	}
	else if(path_str == "/get_gps_data")
	{
		ptree gps_data = get_gps_data();			
		reply =  ptree_to_string(gps_data);
	}
	else if(path_str == "/get_alarm")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		ptree alarm = get_alarm(map_name);			
		reply =  ptree_to_string(alarm);
	}
	else if(path_str == "/get_log")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result;
		ptree log = get_log(map_name);			
		reply =  ptree_to_string(log);
	}
	else if(path_str == "/initialize")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result1 = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result1;
		char *query_result2 = (char*)evhttp_find_header(&params, "init_point_name");
		string init_point_name = query_result2;
		ptree init_info = init_localization(map_name,init_point_name);			
		reply =  ptree_to_string(init_info);
	}
	else if(path_str == "/initialize_status")
	{
		ptree init_status = get_init_status();			
		reply =  ptree_to_string(init_status);
	}
	else if(path_str == "/set_navi_speed")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "level");
		string level = query_result;
		ptree navi_speed = set_navi_speed(level);			
		reply =  ptree_to_string(navi_speed);
	}
	else if(path_str == "/update_navi_info")
	{
		ptree navi_info = update_navi_info();			
		reply =  ptree_to_string(navi_info);
	}
	else if(path_str == "/stop_task")
	{
		ptree stop = stop_task();			
		reply =  ptree_to_string(stop);
	}
	else if(path_str == "/get_task_status")
	{
		ptree task_status = get_task_status();			
		reply =  ptree_to_string(task_status);
	}
		// add by client GenXin 
	else if(path_str == "/connect")
	{
		ptree pt_connect = connect();
		reply =  ptree_to_string(pt_connect);
	}
	else if(path_str == "/control_mode")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "control_mode");
		string mode = query_result;
		//ROS_INFO("set control mode");
		ptree control_mode = set_control_mode(mode);			
		reply =  ptree_to_string(control_mode);
	}
	else if(path_str == "/3d_lidar")
	{
		ptree lidar_3d = get_3d_lidar();			
		reply =  ptree_to_string(lidar_3d);
	}
	else if(path_str == "/2d_lidar")
	{
		ptree lidar_2d = get_2d_lidar();			
		reply =  ptree_to_string(lidar_2d);
	}
	else if(path_str == "/camera")
	{
		ptree camera = get_camera();			
		reply =  ptree_to_string(camera);
	}
	else if(path_str == "/gps")
	{
		ptree gps = get_gps();			
		reply =  ptree_to_string(gps);
	}
	else if(path_str == "/sonar")
	{
		ptree sonar = get_sonar();			
		reply =  ptree_to_string(sonar);
	}
	else if(path_str == "/odom")
	{
		ptree odom = get_odom();			
		reply =  ptree_to_string(odom);
	}
	else if(path_str == "/imu")
	{
		ptree info = get_imu();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/infra")
	{	
		ptree infra = get_infra();			
		reply =  ptree_to_string(infra);
	}
	else if(path_str == "/key")
	{	
		ptree info = get_key();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/rfid")
	{		
		ptree rfid = get_rfid();			
		reply =  ptree_to_string(rfid);
	}
	else if(path_str == "/uwb")
	{	
		ptree uwb = get_uwb();			
		reply =  ptree_to_string(uwb);
	}
	else if(path_str == "/safe_area")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result1 = (char*)evhttp_find_header(&params, "r1");
		string r1 = query_result1;
		char *query_result2 = (char*)evhttp_find_header(&params, "r2");
		string r2 = query_result2;
		char *query_result3 = (char*)evhttp_find_header(&params, "r3");
		string r3 = query_result3;
		//ROS_INFO("r1:%s,r2:%s,r3:%s",r1.c_str(),r2.c_str(),r3.c_str());
		ptree area = set_safe_area(r1,r2,r3);			
		reply =  ptree_to_string(area);
	}
	else if(path_str == "/mapping")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "mode");
		string mode = query_result;
		char *query_result2 = (char*)evhttp_find_header(&params, "map_name");
		string map_name = query_result2;
		ptree mapping = set_mapping_mode(map_name,mode);			
		reply =  ptree_to_string(mapping);
	}
	else if(path_str == "/start_scan")
	{
		ptree info = start_scan();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/cancel_scan")
	{
		ptree info = cancel_scan();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/finish_scan")
	{
		ptree info = finish_scan();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/scan_status")
	{
		ptree info = get_scan_status();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/start_mapping")
	{
		ptree info = start_mapping();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/cancel_mapping")
	{
		ptree info = cancel_mapping();
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/get_mapping_status")
	{
		ptree info = get_mapping_status();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/del_map")
	{
		char *query = const_cast<char*>(query_str.c_str());
		evhttp_parse_query_str(query, &params);			
		char *query_result = (char*)evhttp_find_header(&params, "map_name");

		string map_name = query_result;
		ptree info = del_map(map_name);			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/global_position")
	{
		ptree info = global_position();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/get_running_status")
	{
		ptree info = get_running_status();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/pause_task")
	{
		ptree info = pause_task();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/resume_task")
	{
		ptree info = resume_task();			
		reply =  ptree_to_string(info);
	}
	else if(path_str == "/stop_task")
	{
		ptree info = stop_task();			
		reply =  ptree_to_string(info);
	}
	else
	{
		ptree error_info;
		error_info.put<string>("data","",string_translator<std::string>());
		error_info.put<string>("errorCode","",string_translator<std::string>());
		error_info.put<string>("msg","invalid uri",string_translator<std::string>());
		error_info.put<bool>("successed",false);
		reply =  ptree_to_string(error_info);
	}
	evhttp_add_header(req->output_headers,"Content-Type","application/json;charset=UTF-8");
	evbuffer_add_printf(retbuff,reply.c_str());
	//evbuffer_add(retbuff,reply);
	evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
	evbuffer_free(retbuff);
}

//处理post请求
void http_post_handler(struct evhttp_request *req)
{
	if(req == NULL)
	{
		printf("====line:%d,%s\n",__LINE__,"input param req is null.");
		return;
	}
	
	char buf[BUF_MAX] = {0};
	const char *path_str = get_post_message(buf, req);//获取请求数据，一般是json格式的数据
	string reply;
	struct evbuffer *retbuff = NULL;
	retbuff = evbuffer_new();
	if(buf == NULL)
	{
		printf("====line:%d,%s\n",__LINE__,"get_post_message return null.");
		return;
	}
	string path = path_str;
	ROS_INFO("post path:%s",path.c_str());
	ROS_INFO("post buf:%s",buf);
	if(path == "/set_param")
	{
		ptree param = set_param(buf);
		reply =  ptree_to_string(param);
	}
	else if(path == "/add_navi_point")
	{
		ptree navi_point = add_navi_point(buf);
		reply =  ptree_to_string(navi_point);
	}
	else if(path == "/rename_navi_point")
	{
		ptree navi_point = rename_navi_point(buf);
		reply =  ptree_to_string(navi_point);
	}
	else if(path == "/add_navi_path")
	{
		ptree navi_path = add_navi_path(buf);
		reply =  ptree_to_string(navi_path);
	}
	else if(path == "/add_task")
	{
		ptree task = add_task(buf);
		reply =  ptree_to_string(task);
	}
	else if(path == "/edit_task")
	{
		ptree task = edit_task(buf);
		reply =  ptree_to_string(task);
	}
	else if(path == "/set_default_task")
	{
		ptree task = set_default_task(buf);
		reply =  ptree_to_string(task);
	}
	else if(path == "/move_cmd")
	{
		ptree move_cmd = set_move_cmd(buf);
		reply =  ptree_to_string(move_cmd);
	}
	else if(path == "/navi_to_point")
	{
		ptree point = navi_to_point(buf);			
		reply =  ptree_to_string(point);
	}
	else if(path == "/navi_to_dest")
	{
		ptree dest = navi_to_dest(buf);
		reply =  ptree_to_string(dest);
	}
	else if(path == "/navi_along_path")
	{
		ptree path = navi_along_path(buf);
		reply =  ptree_to_string(path);
	}
	else if(path == "/start_task")
	{
		ptree start = start_task(buf);
		reply =  ptree_to_string(start);
	}
	else if(path == "/update_map")
	{
//		ROS_INFO("download file");
		ptree file = download_file(buf);
		reply =  ptree_to_string(file);
	}
	else if(path == "/init_point")
	{
		ptree init_point = set_init_point(buf);
		reply =  ptree_to_string(init_point);
	}
	else if(path == "/calibration_point")
	{
		ptree calibration_point = set_calibration_point(buf);
		reply =  ptree_to_string(calibration_point);
	}
	else if(path == "/work_point")
	{
		ptree work_point = set_work_point(buf);
		reply =  ptree_to_string(work_point);
	}
	else if(path == "/charge_point")
	{
		ptree charge_point = set_charge_point(buf);
		reply =  ptree_to_string(charge_point);
	}
	else if(path == "/navi_point")
	{
		ptree navi_point = set_navi_point(buf);
		reply =  ptree_to_string(navi_point);
	}
	else if(path == "/user_point")
	{
		ptree user_point = set_user_point(buf);
		reply =  ptree_to_string(user_point);
	}
	else if(path == "/navi_path")
	{
		ptree navi_path = set_navi_path(buf);
		reply =  ptree_to_string(navi_path);
	}
	else if(path == "/virtual_wall")
	{
		ptree virtual_wall = set_virtual_wall(buf);
		reply =  ptree_to_string(virtual_wall);
	}
	else if(path == "/virtual_wall_point")
	{
		ptree virtual_wall_point = set_virtual_wall_point(buf);
		reply =  ptree_to_string(virtual_wall_point);
	}
	else if(path == "/user_path")
	{
		ptree user_path = set_user_path(buf);
		reply =  ptree_to_string(user_path);
	}
	else if(path == "/user_path_point")
	{
		ptree user_path_point = set_user_path_point(buf);
		reply =  ptree_to_string(user_path_point);
	}
	else if(path == "/slow_area")
	{
		ptree slow_area = set_slow_area(buf);
		reply =  ptree_to_string(slow_area);
	}
	else if(path == "/slow_area_point")
	{
		ptree slow_area_point = set_slow_area_point(buf);
		reply =  ptree_to_string(slow_area_point);
	}
	else if(path == "/stop_area")
	{
		ptree stop_area = set_stop_area(buf);
		reply =  ptree_to_string(stop_area);
	}
	else if(path == "/stop_area_point")
	{
		ptree stop_area_point = set_stop_area_point(buf);
		reply =  ptree_to_string(stop_area_point);
	}
	else if(path == "/user_area")
	{
		ptree user_area = set_user_area(buf);
		reply =  ptree_to_string(user_area);
	}
	else if(path == "/user_area_point")
	{
		ptree user_area_point = set_user_area_point(buf);
		reply =  ptree_to_string(user_area_point);
	}
	else if(path == "/initial_position")
	{
		ptree info = initial_position(buf);
		reply =  ptree_to_string(info);
	}
	else if(path == "/task")
	{
		ptree info = start_route(buf);
		reply =  ptree_to_string(info);
	}
	else
	{
		ptree error_info;
		error_info.put<string>("data","",string_translator<std::string>());
		error_info.put<string>("errorCode","",string_translator<std::string>());
		error_info.put<string>("msg","error uri",string_translator<std::string>());
		error_info.put<bool>("successed",false);

		string reply =  ptree_to_string(error_info);
		struct evbuffer *retbuff = NULL;
		retbuff = evbuffer_new();
		evbuffer_add_printf(retbuff,reply.c_str());
		evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
		evbuffer_free(retbuff);
		return ;
	}
	evhttp_add_header(req->output_headers,"Content-Type","application/json;charset=UTF-8");
	evbuffer_add_printf(retbuff,reply.c_str());
	evhttp_send_reply(req,HTTP_OK,"Client",retbuff);
	evbuffer_free(retbuff);
}

int main(int argc,char**argv)
{
    ros::init(argc,argv,"cloud_api");
	ros::NodeHandle nh("~");
	//setlocale(LC_ALL,"");

	cloud_api = new CloudApi(nh);
	sleep(5);
	int port = nh.param<int>("http_port",8082);
	string ip = nh.param<std::string>("http_address","10.7.5.8");
	map_path = nh.param<std::string>("config_file_path","/home/smartgo/config/");
	short http_port = port;
	char *http_addr = const_cast<char*>(ip.c_str());
//	http_server_init(http_addr, http_port);

	httpserver_start(http_port, 10, 10240);

	ros::Rate loop_rate(2);

    while (ros::ok())
    {
        ros::spinOnce();
        loop_rate.sleep();
    }
	//http_server_stop();
	return 0;
}